#pragma once

#include "common.hpp"
#include "threadpool.hpp"

namespace Tcp_Server
{
    const static int backlog = 8;

    class TcpServer : public NoCopy
    {
        using task_t = std::function<std::string(const std::string &)>;

    public:
        /**************TcpServer*****************/
        TcpServer(uint16_t port, task_t func)
            : _listensockfd(-1),
              _port(port),
              _isrun(false),
              _func(func)
        {
        }
        /**************Member*****************/
        void Init()
        {
            // 1.创建套接字
            _listensockfd = socket(AF_INET, SOCK_STREAM, 0);
            if (_listensockfd < 0)
            {
                Local_Log::LOG(Local_Log::LogLever::LFATAL) << "socket error";
                exit(ERR_SOCKET);
            }
            Local_Log::LOG(Local_Log::LogLever::LDEBUG) << "socket success " << _listensockfd;

            // 2.绑定socket信息,IP和端口号
            // 2.1 填充sockaddr_in结构体
            Local_Inetaddr::Inetaddr lo_inet(_port);
            //  2.2 绑定
            int bin_ret = bind(_listensockfd, lo_inet.GetAddrPtr(), lo_inet.GetAddrSize());
            // struct sockaddr_in lo_seraddrptr;
            // memset(&lo_seraddrptr, 0, sizeof(lo_seraddrptr));
            // lo_seraddrptr.sin_family = AF_INET;
            // lo_seraddrptr.sin_addr.s_addr = INADDR_ANY;
            // lo_seraddrptr.sin_port = htons(_port);
            // int bin_ret = bind(_listensockfd, (struct sockaddr *)&lo_seraddrptr, sizeof(lo_seraddrptr));

            if (bin_ret < -1)
            {
                Local_Log::LOG(Local_Log::LogLever::LFATAL) << "bind error";
                exit(ERR_BIND);
            }
            Local_Log::LOG(Local_Log::LogLever::LDEBUG) << "bind success " << _listensockfd;

            // 3.监听
            int lis_ret = listen(_listensockfd, backlog);
            if (lis_ret < -1)
            {
                Local_Log::LOG(Local_Log::LogLever::LFATAL) << "listen error";
                exit(ERR_LISTEN);
            }
            Local_Log::LOG(Local_Log::LogLever::LDEBUG) << "listen success " << _listensockfd;
        }
        void Run()
        {
            _isrun = true;
            while (_isrun)
            {
                // 1.填充sockaddr
                struct sockaddr_in lo_addr;
                socklen_t lo_len = sizeof(sockaddr_in);
                // 2.获取链接

                int lo_sockfd = accept(_listensockfd, (struct sockaddr *)&lo_addr, &lo_len);
                if (lo_sockfd < 0)
                {
                    Local_Log::LOG(Local_Log::LogLever::LWARNING) << "accept error";
                    sleep(10);
                    continue;
                }
                Local_Inetaddr::Inetaddr lo_inet(lo_addr);
                Local_Log::LOG(Local_Log::LogLever::LDEBUG) << "登录: " << lo_inet.GetStrAddr();

                /*****************************************************/
                // // 3.单线程服务
                // Service(lo_sockfd);
                // Local_Log::LOG(Local_Log::LogLever::LDEBUG) << "登出: " << lo_inet.GetStrAddr();

                /*****************************************************/
                // 4.多进程版
                // ChildFork(lo_sockfd, lo_inet.GetStrAddr());

                /*****************************************************/
                // 5.多线程版
                ChildThread(lo_sockfd, lo_inet.GetStrAddr());

                /*****************************************************/
                // 6.线程池版
                // std::string lo_name = lo_inet.GetStrAddr();
                // Local_Thread_Pool::LocalThreadPool<task_t>::GetInstance()->TaskPush([this, lo_sockfd, lo_name]()
                //                                                                     {
                //     this->Service(lo_sockfd);
                //     Local_Log::LOG(Local_Log::LogLever::LDEBUG) << "登出: " << lo_name; });
            }
        }
        void Service(int sockfd)
        {
            char lo_buffer[64];
            while (1)
            {
                memset(lo_buffer, 0, sizeof(lo_buffer));
                ssize_t lo_readsize = read(sockfd, lo_buffer, sizeof(lo_buffer) - 1);
                if (lo_readsize > 0)
                {
                    std::cout << ">>>>>>" << lo_buffer << std::endl;

                    // 测试1：回写数据
                    // std::string lo_echo = "echo # ";
                    // lo_echo += lo_buffer;
                    // write(sockfd, lo_echo.c_str(), lo_echo.size());

                    // 测试2：执行回调函数
                    std::string lo_strin(lo_buffer);
                    std::string lo_strout = _func(lo_strin);
                    write(sockfd, lo_strout.c_str(), lo_strout.size());
                }
                else if (lo_readsize < 0)
                {
                    Local_Log::LOG(Local_Log::LogLever::LFATAL) << "read error ";
                    close(sockfd);
                    break;
                }
                else
                {
                    Local_Log::LOG(Local_Log::LogLever::LFATAL) << "read end ";
                    close(sockfd);
                    break;
                }
            }
        }

    private:
        /*****************************************************/
        // 4.多进程版
        void ChildFork(int sockfd, const std::string &name)
        {
            pid_t child_id = fork();
            if (child_id < 0)
            {
                Local_Log::LOG(Local_Log::LogLever::LERROR) << "fork error ";
                close(sockfd);
                return;
            }
            if (child_id == 0)
            {
                // 子进程
                close(_listensockfd);
                if ((fork()) == 0)
                {
                    Service(sockfd);
                    Local_Log::LOG(Local_Log::LogLever::LDEBUG) << "登出: " << name;
                    exit(SUCCESS);
                }
                close(sockfd);
                exit(SUCCESS);
            }
            else
            {
                // 父进程
                close(sockfd);
                waitpid(-1, 0, 0);
            }
        }

    private:
        /*****************************************************/
        // 5.多线程版
        void ChildThread(int sockfd, const std::string &name)
        {
            // 创建线程
            pthread_t lo_pthid;
            ThreadData *lo_pthdata = new ThreadData(sockfd, name, this);
            int ret_pth_cre = pthread_create(&lo_pthid, NULL, Thread_main, lo_pthdata);
        }

        // 回调函数
        static void *Thread_main(void *args)
        {
            pthread_detach(pthread_self());
            ThreadData *lo_pthdata_ptr = static_cast<ThreadData *>(args);
            lo_pthdata_ptr->_tcp_ser->Service(lo_pthdata_ptr->_sockfd);
            Local_Log::LOG(Local_Log::LogLever::LDEBUG) << "登出: " << lo_pthdata_ptr->_name;
            delete (lo_pthdata_ptr);
            return nullptr;
        }
        //参数类
        struct ThreadData
        {
            int _sockfd;
            std::string _name;
            TcpServer *_tcp_ser;
            ThreadData(int sockfd, const std::string &name, TcpServer *tcp_ser)
                : _sockfd(sockfd),
                  _name(name),
                  _tcp_ser(tcp_ser)
            {
            }
        };

    private:
        int _listensockfd;
        // std::string _ip;
        uint16_t _port;
        bool _isrun;
        task_t _func;
    };
}
